﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Reflection;
using System.ComponentModel;

namespace SPMS.Utility
{
    /// <summary>
    /// 对象处理辅助类
    /// </summary>
    /// <remarks></remarks>
    /// <history>
    /// [zanezeng]   2008-9-23 4:36 PM    Created
    /// </history>
    public static class ObjectUtility
    {
        #region ---Public Method

        /// <summary>
        /// 判断指定的对象是否为指定类型实例
        /// </summary>
        /// <typeparam name="T">类型参数，用于判断的类型</typeparam>
        /// <param name="value">用于判断的对象实例</param>
        /// <returns>
        /// 	<c>true</c>：是同一个类型<br/>
        /// 	<c>false</c>：不是同一种类型
        /// </returns>
        /// <remarks>如果传入的对象实例为Null，总是返回False</remarks>
        /// <history>
        /// [zanezeng]   2008-10-25 0:33    Created
        /// </history>
        public static bool IsInstanceOf<T>( object value )
        {
            //判断是否为空
            if (null == value)
            {
                return false;
            }

            //判断类型
            return typeof( T ).IsInstanceOfType( value );
        }

        /// <summary>
        /// 判断指定的对象是否为指定类型实例
        /// </summary>
        /// <param name="type">用于判断的类型</param>
        /// <param name="value">用于判断的对象实例</param>
        /// <returns>
        /// 	<c>true</c>：是同一个类型<br/>
        /// 	<c>false</c>：不是同一种类型
        /// </returns>
        /// <exception cref="System.ArgumentNullException"><paramref name="type"/>为<c>null</c>引用</exception>
        /// <remarks>如果传入的对象实例为Null，总是返回False</remarks>
        /// <history>
        /// [zanezeng]   2008-10-25 0:44    Created
        /// </history>
        public static bool IsInstanceOf( Type type, object value )
        {
            //判断是否为空
            if (null == type)
            {
                //抛出异常
                throw new ArgumentNullException( "type" );
            }

            //判断是否为空
            if (null == value)
            {
                return false;
            }

            //判断类型
            return type.IsInstanceOfType( value );
        }

        /// <summary>
        /// 获得指定类型的默认值
        /// </summary>
        /// <typeparam name="T">类型参数</typeparam>
        /// <returns>指定类型的默认值</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-10-30 9:44    Created
        /// </history>
        public static T DefaultValue<T>()
        {
            //判断是否为枚举
            if (typeof( T ).IsEnum)
            {
                //获得枚举的所有值
                Array values = Enum.GetValues( typeof( T ) );

                //判断是否有值
                if (values != null && values.Length > 0)
                {
                    //如果有值，则返回第一个值
                    return (T)values.GetValue( 0 );
                }
            }

            //返回默认值
            return default( T );
        }

        /// <summary>
        /// 获得指定类型的默认值
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns>指定类型的默认值</returns>
        /// <remarks></remarks>
        /// <exception cref="System.ArgumentNullException">type为Null</exception>
        /// <history>
        /// [zanezeng]   2008-10-30 9:44    Created
        /// </history>
        public static object DefaultValue( Type type )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( type, "type" );

            //判断是否为值类型
            if (!type.IsValueType)
            {
                //如果不是值类型，则返回默认值NULL
                return null;
            }

            //判断是否为枚举
            if (type.IsEnum)
            {
                //获得枚举的所有值
                Array values = Enum.GetValues( type );

                //判断是否有值
                if (values != null && values.Length > 0)
                {
                    //如果有值，则返回第一个值
                    return values.GetValue( 0 );
                }
            }

            //返回默认值
            return System.Activator.CreateInstance( type );
        }

        /// <summary>
        /// 获得返回当前数组、指针或引用类型包含的或引用的对象的 Type
        /// </summary>
        /// <param name="type">数组类型</param>
        /// <returns>数组、指针或引用类型</returns>
        /// <remarks>如果输入的类型为Null或者输入类型不是数组类型则返回Null</remarks>
        /// <history>
        /// [zanezeng]   2008-10-30 10:04    Created
        /// </history>
        public static Type SafeGetElementType( Type type )
        {
            //判断是否为NULL
            if (null == type)
            {
                return null;
            }

            //返回引用类型
            return type.GetElementType();
        }

        /// <summary>
        /// 获得指定的类型全名的类型信息
        /// </summary>
        /// <param name="typeName">类型的全名</param>
        /// <returns>指定的类型全名的类型信息。如果类型名称为Null或者为空字符串，则返回Null</returns>
        /// <remarks>如果没有检索到对应的类型信息，则返回NULL</remarks>
        /// <history>
        /// [zanezeng]   2008-10-30 10:21    Created
        /// </history>
        public static Type GetTypeByName( string typeName )
        {
            //判断类型名称是否有效
            if (!StringUtility.HasText( typeName ))
            {
                //如果无效返回Null
                return null;
            }

            //尝试直接通过名称解析类型
            Type targetType = Type.GetType( typeName, false, true );

            //返回
            return targetType;
        }

        /// <summary>
        /// 拆卸对象实例
        /// </summary>
        /// <param name="instance">需要拆卸的对象实例</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-1 13:07    Created
        /// </history>
        public static void DisposeObject( ref object instance )
        {
            //转化为IDisposable
            IDisposable dispose = instance as IDisposable;

            //释放
            if (null != dispose)
            {
                dispose.Dispose();
            }

            //设置为空
            instance = null;
        }

        /// <summary>
        /// 将指定的字符串转换为指定类型
        /// </summary>
        /// <typeparam name="T">转换的目标类型参数</typeparam>
        /// <param name="value">需要转换的字符串</param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="throwOnError">转换失败时是否抛出异常</param>
        /// <returns>指定类型的对象，其值由<paramref name="value"/>指定。如果<paramref name="value"/>为Null、空字符串或者仅包含空白，则返回默认值</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 16:12    Created
        /// </history>
        public static T ParseValue<T>( string value, T defaultValue, bool throwOnError )
        {
            return (T)ParseValue( typeof( T ), value, defaultValue, throwOnError );
        }

        /// <summary>
        /// 将指定的字符串转换为指定类型
        /// </summary>
        /// <param name="type">目标类型</param>
        /// <param name="value">需要转换的字符串</param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="throwOnError">转换失败时是否抛出异常</param>
        /// <returns>
        /// 指定类型的对象，其值由<paramref name="value"/>指定。如果<paramref name="value"/>为Null、空字符串或者仅包含空白，则返回默认值
        /// </returns>
        /// <exception cref="System.ArgumentNullException"><paramref name="type"/>为Null</exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 16:12    Created
        /// </history>
        public static object ParseValue( Type type, string value, object defaultValue, bool throwOnError )
        {
            try
            {
                //断言参数
                ArgumentAssert.AssertArgumentNotNull( type, "type" );

                //判断是否包含文字
                if (!StringUtility.HasText( value ))
                {
                    return defaultValue;
                }

                //判断是否为基本类型
                if (IsCommonType( type ))
                {
                    return Convert.ChangeType( value, type );
                }

                //获得Parse方法
                MethodInfo method = type.GetMethod( "Parse", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof( string ) }, null );

                //判断是否实现了Parse方法
                if (null != method && method.ReturnType != typeof( void ))
                {
                    //调用方法
                    return method.Invoke( null, new object[] { value } );
                }

                //获得类型转换器
                TypeConverter converter = TypeDescriptor.GetConverter( type );

                //判断是否实现了类型转换接口
                if (null != converter && converter.CanConvertFrom( typeof( string ) ))
                {
                    return converter.ConvertFromString( value );
                }

                //返回默认值
                return defaultValue;
            }
            catch
            {
                //判断是否抛出异常
                if (throwOnError)
                {
                    //抛出异常
                    throw;
                }

                //返回默认值
                return defaultValue;
            }
        }

        /// <summary>
        /// 将指定的字符串解析为枚举
        /// </summary>
        /// <typeparam name="T">转换的目标枚举类型</typeparam>
        /// <param name="value">需要解析成为枚举的字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="throwOnError">转换失败时是否抛出异常。如果设定为FALSE，则转化失败时返回默认值</param>
        /// <returns>
        /// 指定类型的枚举对象，其值由<paramref name="value"/>指定。如果<paramref name="value"/>为Null、空字符串或者仅包含空白，则返回默认值
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 16:00    Created
        /// </history>
        public static T ParseEnum<T>( string value, T defaultValue, bool throwOnError )
        {
            //判断是否包含文字
            if (!StringUtility.HasText( value ))
            {
                return defaultValue;
            }

            try
            {
                //解析
                return (T)Enum.Parse( typeof( T ), value );
            }
            catch
            {
                //判断是否抛出异常
                if (throwOnError)
                {
                    //抛出异常
                    throw;
                }

                //如果不允许抛出异常，则返回默认值
                return defaultValue;
            }
        }

        /// <summary>
        /// 判断指定的类型是否为基本类型
        /// </summary>
        /// <param name="type">用于检查的类型</param>
        /// <returns>
        /// 	<c>true</c>：是基本类型<br/>
        /// 	<c>false</c>：不是基本类型
        /// </returns>
        /// <remarks>如果传入的类型为Null，则返回False</remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 16:28    Created
        /// </history>
        public static bool IsCommonType( Type type )
        {
            //判断是否为Null
            if (null == type)
            {
                return false;
            }

            //判断是否为基本类型
            if (-1 != Array.IndexOf<Type>( s_CommonTypes, type ))
            {
                return true;
            }

            //默认返回不是
            return false;
        }

        /// <summary>
        /// 判断指定的类型是否为基本类型
        /// </summary>
        /// <typeparam name="T">类型参数</typeparam>
        /// <returns>
        /// 	<c>true</c>：是基本类型<br/>
        /// 	<c>false</c>：不是基本类型
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 16:27    Created
        /// </history>
        public static bool IsCommonType<T>()
        {
            return IsCommonType( typeof( T ) );
        }

        /// <summary>
        /// 将指定的对象转化为目标类型
        /// </summary>
        /// <param name="instance">需要转化的对象</param>
        /// <param name="destinationType">转化的目标类型</param>
        /// <returns>转化后的与目标类型一致的对象</returns>
        /// <remarks>如果<paramref name="instance"/>为Null，那么总是返回Null。</remarks>
        /// <exception cref="System.ArgumentNullException"><paramref name="destinationType"/>为Null</exception>
        /// <exception cref="System.InvalidCastException"><paramref name="instance"/>无法转化为目标类型</exception>
        /// <history>
        /// [zanezeng]   2008-11-10 16:18    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-14 15:33    Created
        /// </history>
        public static object ConvertTo( object instance, Type destinationType )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( destinationType, "destinationType" );

            //判断是否为Null
            if (null == instance)
            {
                //如果是Null不需要进行转化
                return instance;
            }

            //判断目标类型是否为字符串
            if (destinationType == typeof( string ))
            {
                //返回字符串
                return instance.ToString();
            }

            //获得实例的类型
            Type sourceType = instance.GetType();

            //判断类型是否兼容
            if (destinationType.IsAssignableFrom( sourceType ))
            {
                return instance;
            }

            //判断是否设置了类型转化器
            TypeConverter converter = TypeDescriptor.GetConverter( sourceType );

            //判断是否允许转化
            if (null != converter && converter.CanConvertTo( destinationType ))
            {
                //执行转化
                return converter.ConvertTo( null, CultureInfo.InvariantCulture, instance, destinationType );
            }

            //获得目标类型的转化器
            converter = TypeDescriptor.GetConverter( destinationType );

            //判断是否存在转化器
            if (null != converter && converter.CanConvertFrom( sourceType ))
            {
                //返回是否允许转化
                return converter.ConvertFrom( null, CultureInfo.InvariantCulture, instance );
            }

            //判断实例是否为字符串
            if (instance is string)
            {
                //查找静态的Parse方法
                MethodInfo parseMethod = destinationType.GetMethod( "Parse", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof( string ) }, null );

                //判断是否存在Parse方法
                if (null != parseMethod)
                {
                    //如果存在Parse方法，则调用Parse方法进行解析
                    return parseMethod.Invoke( null, new object[] { instance } );
                }
            }

            //强制转化
            return Convert.ChangeType( instance, destinationType );
        }

        /// <summary>
        /// 将指定的对象转化为目标类型
        /// </summary>
        /// <typeparam name="T">目标类型泛型类型参数</typeparam>
        /// <param name="instance">需要进行类型转化的对象</param>
        /// <returns>转化后的与目标类型一致的对象</returns>
        /// <remarks>如果<paramref name="instance"/>为Null，那么总是返回Null。</remarks>
        /// <exception cref="System.ArgumentNullException"><paramref name="destinationType"/>为Null</exception>
        /// <exception cref="System.InvalidCastException"><paramref name="instance"/>无法转化为目标类型</exception>
        /// <history>
        /// [zanezeng]   2008-11-10 16:18    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-14 15:33    Created
        /// </history>
        public static T ConvertTo<T>( object instance )
        {
            //判断要转换的对象是否为空引用
            if (null == instance)
            {
                //如果是空引用，则不需要进行转化
                return default( T );
            }

            //返回
            return (T)ConvertTo( instance, typeof( T ) );
        }

        /// <summary>
        /// 尝试将给定的对象转化为目标类型
        /// </summary>
        /// <typeparam name="T">目标类型泛型类型参数</typeparam>
        /// <param name="instance">需要进行类型转化的对象</param>
        /// <param name="result">用于返回转换的结果</param>
        /// <returns>
        /// 	如果转化成功，则返回<c>true</c>，否则返回<c>false</c>。
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 16:28    创建
        /// </history>
        public static bool TryConvertTo<T>( object instance, out T result )
        {
            //设置默认值
            result = default( T );

            //判断要转换的对象是否为空引用
            if (null == instance)
            {
                //如果为空引用，则直接返回转换成功
                return true;
            }

            try
            {
                //进行转换
                result = (T)ConvertTo( instance, typeof( T ) );

                //返回转换成功
                return true;
            }
            catch
            {
                //返回转换失败
                return false;
            }
        }

        /// <summary>
        /// 尝试将给定的对象转化为目标类型
        /// </summary>
        /// <param name="instance">需要进行类型转化的对象</param>
        /// <param name="destinationType">转化的目标类型</param>
        /// <param name="result">用于返回转换的结果</param>
        /// <returns>如果转化成功，则返回<c>true</c>，否则返回<c>false</c>。</returns>
        /// <remarks></remarks>
        /// <exception cref="System.ArgumentNullException"><paramref name="destinationType"/>为Null</exception>
        /// <history>
        /// [zanezeng]               2010/1/13 16:28    创建
        /// </history>
        public static bool TryConvertTo( object instance, Type destinationType, out object result )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( destinationType, "destinationType" );

            //设置默认值
            result = null;

            //判断要转换的对象是否为空引用
            if (null == instance)
            {
                //如果为空引用，则直接返回转换成功
                return true;
            }

            try
            {
                //进行转换
                result = ConvertTo( instance, destinationType );

                //返回转换成功
                return true;
            }
            catch
            {
                //返回转换失败
                return false;
            }
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得空的对象数组
        /// </summary>
        /// <value>空的对象数组</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-10-30 9:37    Created
        /// </history>
        public static object[] EmptyObjects
        {
            get
            {
                return s_EmptyObjects;
            }
        }

        /// <summary>
        /// 获得对象类型
        /// </summary>
        /// <value>对象类型</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009-3-23 15:07    创建
        /// </history>
        public static Type ObjectType
        {
            get
            {
                return s_ObjectType;
            }
        }

        /// <summary>
        /// 获得无限的TimeSpan
        /// </summary>
        /// <value>无限的TimeSpan</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-6 15:30    Created
        /// </history>
        public static TimeSpan Infinity
        {
            get
            {
                return s_Infinity;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 空的对象数组
        /// </summary>
        private static readonly object[] s_EmptyObjects = new object[0];

        /// <summary>
        /// 对象类型
        /// </summary>
        private static readonly Type s_ObjectType = typeof( object );

        /// <summary>
        /// 无限的TimeSpan
        /// </summary>
        private static readonly TimeSpan s_Infinity = new TimeSpan( 0, 0, 0, 0, -1 );

        /// <summary>
        /// 基本类型
        /// </summary>
        private static readonly Type[] s_CommonTypes = new Type[] 
        { 
            typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(DateTime), typeof(string)
        };

        #endregion
    }
}
